<?php
/**
 * @package trading
 */
class TradeOrder extends DataObject implements PermissionProvider {
    private static $singular_name = "Trade Order";
    private static $plural_name = "Trade Orders";

    private static $db = array(
        'Type' => "Enum(array('Buy', 'Sell'))",
        'Reference' => 'Varchar',
        'Unit' => 'Int',
        'Remaining' => 'Int',
        'Price' => 'TradeCurrency',
        'FeePercentage' => 'Percentage',
        'Status' => "Enum(array('Pending', 'Cancelled', 'Completed'))"
    );

    private static $has_one = array(
        'Member' => 'Member',
        'TradeSetting' => 'TradeSetting'
    );
	
	private static $many_many = array(
		'BonusAccounts' => 'BonusAccount',
		'ProductAccounts' => 'ProductAccount',
        'TradeCoinAccounts' => 'TradeCoinAccount',
		'Requesters' => 'TradeOrder',
		'TradeHistories' => 'TradeHistory'
	);

    private static $default_sort = "Created DESC";

    private static $searchable_fields = array(
    	'Created' => array(
			'field' => 'DateField',
			'filter' => 'DateMatchFilter'
		),
    	'Member.Username',
    	'Member.FirstName',
    	'Member.Surname',
        'Type',
        'Reference',
        'Unit' => array(
            'filter' => 'GreaterThanOrEqualFilter'
        ),
        'Price' => array(
            'filter' => 'GreaterThanOrEqualFilter'
        ),
        'Status'
    );

    private static $summary_fields = array(
    	'Member.Username',
    	'Member.Name',
    	'Created.Nice',
        'Type',
        'Reference',
        'Unit',
        'Price',
        'Fee',
        'Status'
    );
	
	private static $casting = array(
		'Amount' => 'TradeCurrency',
		'RemainAmount' => 'TradeCurrency',
		'Fee' => 'TradeCurrency',
		'RemainFee' => 'TradeCurrency'
	);
	
	/**
     * Generate reference for trade order
     * @return str Returns the reference
     */
    static function reference_generator() {
        $reference = rand(1, 99999999);
        $reference = str_pad($reference, 8, "0", STR_PAD_LEFT);
        while($result = TradeOrder::get()->filter('Reference', $reference)->count()) {
            $reference = rand(1, 999999999);
            $reference = str_pad($reference, 8, "0", STR_PAD_LEFT);
        }
        return $reference;
    }

    public function populateDefaults() {
        parent::populateDefaults();
		$this->Status = 'Pending';
    }

    public function fieldLabels($includerelations = true) {
        $labels = parent::fieldLabels($includerelations);

		$labels['Created'] = _t('TradeOrder.DATE', 'Date');
		$labels['Created.Nice'] = _t('TradeOrder.DATE', 'Date');
        $labels['Type'] = _t('TradeOrder.TYPE', 'Type');
		$labels['Reference'] = _t('TradeOrder.REFERENCE', 'Reference');
        $labels['Unit'] = _t('TradeOrder.UNIT', 'Unit');
		$labels['Remaining'] = _t('TradeOrder.REMAINING', 'Remaining');
        $labels['Price'] = _t('TradeOrder.PRICE', 'Price');
		$labels['Fee'] = _t('TradeOrder.FEE', 'Fee');
		$labels['FeePercentage'] = _t('TradeOrder.FEE_PERCENTAGE', 'Fee Percentage');
        $labels['Status'] = _t('TradeOrder.STATUS', 'Status');
		$labels['TradeSetting'] = _t('TradeOrder.TRADE_SETTING', 'Trade Setting');
		$labels['TradeSettingID'] = _t('TradeOrder.TRADE_SETTING', 'Trade Setting');
		$labels['Member.Username'] = _t('TradeOrder.USERNAME', 'Username');
		$labels['Member.FirstName'] = _t('TradeOrder.FIRST_NAME', 'First Name');
		$labels['Member.Surname'] = _t('TradeOrder.SURNAME', 'Surname');
		$labels['Member.Name'] = _t('TradeOrder.NAME', 'Name');
		$labels['Member'] = _t('TradeOrder.NAME', 'Name');

        return $labels;
    }

    function validate() {
        $validationResult = parent::validate();

        if(!$this->MemberID) {
            $subvalid = new ValidationResult();
            $subvalid->error(_t('TradeOrder.INVALID_MEMBER_ID', 'Invalid Member ID'), 'INVALID_MEMBER_ID');
            $validationResult->combineAnd($subvalid);
        } else { 
        	if(!$this->exists() && $this->Type == 'Sell' && $this->Unit > $this->Member()->TradeAccount($this->TradeSettingID)->AvailableUnit) {
	            $subvalid = new ValidationResult();
	            $subvalid->error(_t('TradeOrder.INSUFFICIENT_AVAILABLE_TRADE_UNIT', "Insufficient available trade unit"), "INSUFFICIENT_AVAILABLE_TRADE_UNIT");
	            $validationResult->combineAnd($subvalid);
            }
			else if(!$this->exists() && $this->Type == 'Buy' && ($this->Amount + $this->Fee) > $this->Member()->TradeCoinAccountBalance) {
	            $subvalid = new ValidationResult();
	            $subvalid->error(_t('TradeOrder.INSUFFICIENT_TRADE_COIN_BALANCE', "Insufficient Trade-Coin balance"), "INSUFFICIENT_TRADE_COIN_BALANCE");
	            $validationResult->combineAnd($subvalid);
            }
        }
		
		if(!$this->Type) {
            $subvalid = new ValidationResult();
            $subvalid->error(_t('TradeOrder.INVALID_TRADE_TYPE', 'Invalid trade type'), 'INVALID_TRADE_TYPE');
            $validationResult->combineAnd($subvalid);
        }

        if($this->Unit <= 0) {
            $subvalid = new ValidationResult();
            $subvalid->error(_t('TradeOrder.INVALID_TRADE_UNIT', 'Invalid trade unit'), 'INVALID_TRADE_UNIT');
            $validationResult->combineAnd($subvalid);
        }

        if($this->Price <= 0) {
            $subvalid = new ValidationResult();
            $subvalid->error(_t('TradeOrder.INVALID_TRADE_PRICE', 'Invalid trade price'), 'INVALID_TRADE_PRICE');
            $validationResult->combineAnd($subvalid);
        }
		else {
			if(!$this->exists() && (($this->Type == 'Buy' && $this->TradeSetting()->ForceBuyingPrice) || ($this->Type == 'Sell' && $this->TradeSetting()->ForceSellingPrice)) && $this->Price != $this->TradeSetting()->Price){
				$subvalid = new ValidationResult();
	            $subvalid->error(_t('TradeOrder.INVALID_TRADE_PRICE', 'Invalid trade price'), 'INVALID_TRADE_PRICE');
	            $validationResult->combineAnd($subvalid);
			}
			
			if(!$this->exists() && (($this->Type == 'Buy' && !$this->TradeSetting()->ForceBuyingPrice) || ($this->Type == 'Sell' && !$this->TradeSetting()->ForceSellingPrice)) && $this->Price < $this->TradeSetting()->Price){
				$subvalid = new ValidationResult();
	            $subvalid->error(_t('TradeOrder.LOWER_TRADE_PRICE', 'Trade price cannot less than current market price'), 'LOWER_TRADE_PRICE');
	            $validationResult->combineAnd($subvalid);
			}
		}
		
		if($this->FeePercentage < 0) {
            $subvalid = new ValidationResult();
            $subvalid->error(_t('TradeOrder.INVALID_TRADE_FEE_PERCENTAGE', 'Invalid trade fee percentage'), 'INVALID_TRADE_FEE_PERCENTAGE');
            $validationResult->combineAnd($subvalid);
        }
		
		if($this->Remaining < 0) {
            $subvalid = new ValidationResult();
            $subvalid->error(_t('TradeOrder.INVALID_TRADE_REMAINING', 'Invalid trade remaining'), 'INVALID_TRADE_REMAINING');
            $validationResult->combineAnd($subvalid);
        }
		
		if(!$this->TradeSettingID) {
            $subvalid = new ValidationResult();
            $subvalid->error(_t('TradeOrder.INVALID_TRADE_SETTING_ID', 'Invalid trade setting id'), 'INVALID_TRADE_SETTING_ID');
            $validationResult->combineAnd($subvalid);
        }
		else if(!$this->TradeSetting()->IsActive || !$this->TradeSetting()->IsStarted || $this->TradeSetting()->IsClosed){
			$subvalid = new ValidationResult();
            $subvalid->error(_t('TradeOrder.TRADE_MARKET_CLOSE', 'Sorry, currently trade market is closed'), 'TRADE_MARKET_CLOSE');
            $validationResult->combineAnd($subvalid);
		}
		
		if(!$this->exists() && $this->FeePercentage > 0 && (($this->FeePercentage != $this->TradeSetting()->BuyFeePercentage && $this->Type == 'Buy') || ($this->FeePercentage != $this->TradeSetting()->SellFeePercentage && $this->Type == 'Sell'))){
			$subvalid = new ValidationResult();
            $subvalid->error(_t('TradeOrder.INVALID_TRADE_FEE_PERCENTAGE', 'Invalid trade fee percentage'), 'INVALID_TRADE_FEE_PERCENTAGE');
            $validationResult->combineAnd($subvalid);
		}

		if(!$this->exists() && $this->Unit > 0 && $this->TradeSettingID > 0 && $this->Price > 0 && $this->Type == 'Buy' && $this->Unit > TradeSetting::get_available_unit_by_price($this->TradeSettingID, $this->Price)){
			$subvalid = new ValidationResult();
            $subvalid->error(_t('TradeOrder.INSUFFICIENT_TRADE_UNIT', 'Insufficient available trade unit'), 'INSUFFICIENT_TRADE_UNIT');
            $validationResult->combineAnd($subvalid);
		}
		
		if(!$this->exists() && $this->Unit > 0 && $this->TradeSettingID > 0 && $this->Price > 0 && $this->Type == 'Sell' && $this->Unit > TradeSetting::get_limit_member_unit_by_price($this->TradeSettingID, $this->Price)){
			$subvalid = new ValidationResult();
            $subvalid->error(_t('TradeOrder.EXCEED_SELL_TRADE_UNIT_LIMIT', 'Exceed sell trade unit limit'), 'EXCEED_SELL_TRADE_UNIT_LIMIT');
            $validationResult->combineAnd($subvalid);
		}

        return $validationResult;
    }

	function getCMSFields() {
        $fields = parent::getCMSFields();

        if(!$this->exists()){
            $fields->insertBefore(UsernameField::create('SetUsername', $this->fieldLabel('Member.Username')), 'Type');
			$fields->removeByName('Reference');
			$fields->removeByName('Remaining');
			$fields->removeByName('Status');
			$fields->removeByName('MemberID');
        }
		else{
			$fields->makeFieldReadonly('Reference');
			$fields->makeFieldReadonly('Remaining');
			$fields->makeFieldReadonly('Status');
			
			$fields->removeByName('BonusAccounts');
			$fields->removeByName('ProductAccounts');
			$fields->removeByName('TradeCoinAccounts');
			$fields->removeByName('Requesters');
			$fields->removeByName('TradeHistories');
		}

        return $fields;
    }

	function onBeforeWrite() {
        parent::onBeforeWrite();
        if(!$this->exists() && $this->Status == 'Pending'){
			$this->Remaining = $this->Unit;
		}
		
        if($this->Reference == '') {
            $this->Reference = self::reference_generator();
        }
		
		if($this->SetUsername){
			$this->MemberID = Distributor::get_id_by_username($this->SetUsername);
		}
		
		if($this->Remaining == 0){
			$this->Status = 'Completed';
		}
    }

    function onAfterWrite() {
        parent::onAfterWrite();
		
        if($this->isChanged('ID') && $this->Type == 'Buy'){
        	if($this->Amount > 0){
	        	$statement_data = array(
	                'Type' => 'Buy Share',
	                'Debit' => $this->Amount + $this->Fee,
	                'Reference' => $this->Reference,
	                'Description' => sprintf('Buy order with %s units at price %s of share %s. Fees %s.', $this->dbObject('Unit')->Formatted(), $this->dbObject('Price')->Nice(), $this->Name, $this->obj('Fee')->Nice())
	            );
	        	$id = TradeCoinAccount::create_statement($statement_data, $this->MemberID);
				$this->TradeCoinAccounts()->add($id);
			}
			
			$available_company_unit = TradeSetting::get_available_company_unit_by_price($this->TradeSettingID, $this->Price);
			if($available_company_unit > 0){
				if($available_company_unit >= $this->Remaining){
					$trade_history = TradeHistory::create();
					$trade_history->Type = 'Buy';
					$trade_history->Reference = $this->Reference;
					$trade_history->Unit = $this->Remaining;
					$trade_history->Price = $this->Price;
					$trade_history->Fee = $this->FeePercentage * $trade_history->Unit * $trade_history->Price;
					$trade_history->MemberID = $this->MemberID;
					$trade_history->TradeSettingID = $this->TradeSettingID;
					$trade_history->IsCompany = 1;
					$trade_history->write();
					$this->TradeHistories()->add($trade_history);
					$this->Remaining = 0;
					$this->write();
				}
				else{
					$trade_history = TradeHistory::create();
					$trade_history->Type = 'Buy';
					$trade_history->Reference = $this->Reference;
					$trade_history->Unit = $available_company_unit;
					$trade_history->Price = $this->Price;
					$trade_history->Fee = $this->FeePercentage * $trade_history->Unit * $trade_history->Price;
					$trade_history->MemberID = $this->MemberID;
					$trade_history->TradeSettingID = $this->TradeSettingID;
					$trade_history->IsCompany = 1;
					$trade_history->write();
					$this->TradeHistories()->add($trade_history);
					$this->Remaining -= $available_company_unit;
				}
			}
			
            $trade_orders = TradeOrder::get()->filter('TradeSettingID', $this->TradeSettingID)->filter('Type', 'Sell')->filter('Remaining:GreaterThan', 0)->filter('Price', $this->Price)->filter('Status', 'Pending')->sort('Created');
			if($trade_orders->count() > 0 && $this->Remaining > 0){
				foreach($trade_orders as $trade_order){
					if($trade_order->Remaining >= $this->Remaining){
						$trade_history = TradeHistory::create();
						$trade_history->Type = 'Sell';
						$trade_history->Reference = $trade_order->Reference;
						$trade_history->Unit = $this->Remaining;
						$trade_history->Price = $trade_order->Price;
						$trade_history->Fee = $trade_order->FeePercentage * $trade_history->Unit * $trade_history->Price;
						$trade_history->MemberID = $trade_order->MemberID;
						$trade_history->TradeSettingID = $trade_order->TradeSettingID;
						$trade_history->write();
						$trade_order->TradeHistories()->add($trade_history);
						
						$statement_data = array(
				            'Type' => 'Sell Share',
				            'Credit' => $trade_history->Amount * 0.5,
				            'Reference' => $trade_history->Reference,
				            'Description' => sprintf('Sell %s units of %s share at %s per unit. Fees %s, %s receivable.', $trade_history->dbObject('Unit')->Formatted(), $trade_history->Name, $trade_history->dbObject('Price')->Nice(), $trade_history->dbObject('Fee')->Nice(), DBField::create_field('Percentage', 0.5)->Nice())
				        );
						
				    	$id = BonusAccount::create_statement($statement_data, $trade_history->MemberID);
						$this->BonusAccounts()->add($id);
						
						$statement_data = array(
				            'Type' => 'Sell Share',
				            'Credit' => ($trade_history->Amount - $trade_history->Fee) * 0.1,
				            'Reference' => $trade_history->Reference,
				            'Description' => sprintf('Sell %s units of %s share at %s per unit. Fees %s, %s receivable.', $trade_history->dbObject('Unit')->Formatted(), $trade_history->Name, $trade_history->dbObject('Price')->Nice(), $trade_history->dbObject('Fee')->Nice(), DBField::create_field('Percentage', 0.1)->Nice())
				        );
						
				    	$id = ProductAccount::create_statement($statement_data, $trade_history->MemberID);
						$this->ProductAccounts()->add($id);
						
						$statement_data = array(
				            'Type' => 'Sell Share',
				            'Credit' => ($trade_history->Amount - $trade_history->Fee) * 0.3,
				            'Reference' => $trade_history->Reference,
				            'Description' => sprintf('Sell %s units of %s share at %s per unit. Fees %s, %s receivable.', $trade_history->dbObject('Unit')->Formatted(), $trade_history->Name, $trade_history->dbObject('Price')->Nice(), $trade_history->dbObject('Fee')->Nice(), DBField::create_field('Percentage', 0.3)->Nice())
				        );
				    	$id = TradeCoinAccount::create_statement($statement_data, $trade_history->MemberID);
						$this->TradeCoinAccounts()->add($id);
						
						$trade_history = TradeHistory::create();
						$trade_history->Type = 'Buy';
						$trade_history->Reference = $this->Reference;
						$trade_history->Unit = $this->Remaining;
						$trade_history->Price = $trade_order->Price;
						$trade_history->Fee = $this->FeePercentage * $trade_history->Unit * $trade_history->Price;
						$trade_history->MemberID = $this->MemberID;
						$trade_history->TradeSettingID = $this->TradeSettingID;
						$trade_history->write();
						$this->TradeHistories()->add($trade_history);
						
						$trade_order->Remaining -= $this->Remaining;
						$trade_order->write();
						
						$this->Requesters()->add($trade_order);
						$this->Remaining = 0;
						break;
					}
					else {
						$trade_history = TradeHistory::create();
						$trade_history->Type = 'Sell';
						$trade_history->Reference = $trade_order->Reference;
						$trade_history->Unit = $trade_order->Remaining;
						$trade_history->Price = $trade_order->Price;
						$trade_history->Fee = $trade_order->FeePercentage * $trade_history->Unit * $trade_history->Price;
						$trade_history->MemberID = $trade_order->MemberID;
						$trade_history->TradeSettingID = $trade_order->TradeSettingID;
						$trade_history->write();
						$trade_order->TradeHistories()->add($trade_history);
						
						$statement_data = array(
				            'Type' => 'Sell Share',
				            'Credit' => $trade_history->Amount * 0.5,
				            'Reference' => $trade_history->Reference,
				            'Description' => sprintf('Sell %s units of %s share at %s per unit. Fees %s, %s receivable.', $trade_history->dbObject('Unit')->Formatted(), $trade_history->Name, $trade_history->dbObject('Price')->Nice(), $trade_history->dbObject('Fee')->Nice(), DBField::create_field('Percentage', 0.5)->Nice())
				        );
				    	$id = BonusAccount::create_statement($statement_data, $trade_history->MemberID);
						$this->BonusAccounts()->add($id);
						
						$statement_data = array(
				            'Type' => 'Sell Share',
				            'Credit' => $trade_history->Amount * 0.1,
				            'Reference' => $trade_history->Reference,
				            'Description' => sprintf('Sell %s units of %s share at %s per unit. Fees %s, %s receivable.', $trade_history->dbObject('Unit')->Formatted(), $trade_history->Name, $trade_history->dbObject('Price')->Nice(), $trade_history->dbObject('Fee')->Nice(), DBField::create_field('Percentage', 0.1)->Nice())
				        );
				    	$id = ProductAccount::create_statement($statement_data, $trade_history->MemberID);
						$this->ProductAccounts()->add($id);
						
						$statement_data = array(
				            'Type' => 'Sell Share',
				            'Credit' => ($trade_history->Amount - $trade_history->Fee) * 0.3,
				            'Reference' => $trade_history->Reference,
				            'Description' => sprintf('Sell %s units of %s share at %s per unit. Fees %s, %s receivable.', $trade_history->dbObject('Unit')->Formatted(), $trade_history->Name, $trade_history->dbObject('Price')->Nice(), $trade_history->dbObject('Fee')->Nice(), DBField::create_field('Percentage', 0.3)->Nice())
				        );
				    	$id = TradeCoinAccount::create_statement($statement_data, $trade_history->MemberID);
						$this->TradeCoinAccounts()->add($id);
						
						$trade_history = TradeHistory::create();
						$trade_history->Type = 'Buy';
						$trade_history->Reference = $this->Reference;
						$trade_history->Unit = $trade_order->Remaining;
						$trade_history->Price = $trade_order->Price;
						$trade_history->Fee = $this->FeePercentage * $trade_history->Unit * $trade_history->Price;
						$trade_history->MemberID = $this->MemberID;
						$trade_history->TradeSettingID = $this->TradeSettingID;
						$trade_history->write();
						$this->TradeHistories()->add($trade_history);
						
						$this->Remaining -= $trade_order->Remaining;
						
						$trade_order->Remaining = 0;
						$trade_order->write();
						
						$this->Requesters()->add($trade_order);
					}
				}
				$this->write();
			}
        }

		if($this->isChanged('Status') && $this->Status == 'Cancelled' && $this->Type == 'Buy'){
			if($this->RemainAmount > 0){
				$statement_data = array(
	                'Type' => 'Buy Share',
	                'Credit' => $this->RemainAmount + $this->RemainFee,
	                'Reference' => $this->Reference,
	                'Description' => sprintf('Refunded from cancelled buy order with %s remaining units at price %s of share %s. Fees %s.', $this->dbObject('Remaining')->Formatted(), $this->dbObject('Price')->Nice(), $this->Name, $this->obj('RemainFee')->Nice())
	            );
	        	$id = TradeCoinAccount::create_statement($statement_data, $this->MemberID);
				$this->TradeCoinAccounts()->add($id);
			}
		}
		
		if($this->isChanged('ID') && $this->Type == 'Sell'){
			$trade_orders = TradeOrder::get()->filter('TradeSettingID', $this->TradeSettingID)->filter('Type', 'Buy')->filter('Remaining:GreaterThan', 0)->filter('Price', $this->Price)->filter('Status', 'Pending')->sort('Created');
			if($trade_orders->count() > 0){
				foreach($trade_orders as $trade_order){
					if($trade_order->Remaining >= $this->Remaining){
						$trade_history = TradeHistory::create();
						$trade_history->Type = 'Sell';
						$trade_history->Reference = $this->Reference;
						$trade_history->Unit = $this->Remaining;
						$trade_history->Price = $this->Price;
						$trade_history->Fee = $this->FeePercentage * $trade_history->Unit * $trade_history->Price;
						$trade_history->MemberID = $this->MemberID;
						$trade_history->TradeSettingID = $this->TradeSettingID;
						$trade_history->write();
						$this->TradeHistories()->add($trade_history);
						
						$statement_data = array(
				            'Type' => 'Sell Share',
				            'Credit' => $trade_history->Amount * 0.5,
				            'Reference' => $trade_history->Reference,
				            'Description' => sprintf('Sell %s units of %s share at %s per unit. Fees %s, %s receivable.', $trade_history->dbObject('Unit')->Formatted(), $trade_history->Name, $trade_history->dbObject('Price')->Nice(), $trade_history->dbObject('Fee')->Nice(), DBField::create_field('Percentage', 0.5)->Nice())
				        );
				    	$id = BonusAccount::create_statement($statement_data, $trade_history->MemberID);
						$this->BonusAccounts()->add($id);
						
						$statement_data = array(
				            'Type' => 'Sell Share',
				            'Credit' => $trade_history->Amount * 0.1,
				            'Reference' => $trade_history->Reference,
				            'Description' => sprintf('Sell %s units of %s share at %s per unit. Fees %s, %s receivable.', $trade_history->dbObject('Unit')->Formatted(), $trade_history->Name, $trade_history->dbObject('Price')->Nice(), $trade_history->dbObject('Fee')->Nice(), DBField::create_field('Percentage', 0.1)->Nice())
				        );
				    	$id = ProductAccount::create_statement($statement_data, $trade_history->MemberID);
						$this->ProductAccounts()->add($id);
						
						$statement_data = array(
				            'Type' => 'Sell Share',
				            'Credit' => $trade_history->Amount * 0.3,
				            'Reference' => $trade_history->Reference,
				            'Description' => sprintf('Sell %s units of %s share at %s per unit. Fees %s, %s receivable.', $trade_history->dbObject('Unit')->Formatted(), $trade_history->Name, $trade_history->dbObject('Price')->Nice(), $trade_history->dbObject('Fee')->Nice(), DBField::create_field('Percentage', 0.3)->Nice())
				        );
				    	$id = TradeCoinAccount::create_statement($statement_data, $trade_history->MemberID);
						$this->TradeCoinAccounts()->add($id);
						
						$trade_history = TradeHistory::create();
						$trade_history->Type = 'Buy';
						$trade_history->Reference = $trade_order->Reference;
						$trade_history->Unit = $this->Remaining;
						$trade_history->Price = $this->Price;
						$trade_history->Fee = $trade_order->FeePercentage * $trade_history->Unit * $trade_history->Price;
						$trade_history->MemberID = $trade_order->MemberID;
						$trade_history->TradeSettingID = $trade_order->TradeSettingID;
						$trade_history->write();
						$trade_order->TradeHistories()->add($trade_history);
						
						$trade_order->Remaining -= $this->Remaining;
						$trade_order->write();
						
						$this->Requesters()->add($trade_order);
						$this->Remaining = 0;
						break;
					}
					else {
						$trade_history = TradeHistory::create();
						$trade_history->Type = 'Sell';
						$trade_history->Reference = $this->Reference;
						$trade_history->Unit = $trade_order->Remaining;
						$trade_history->Price = $this->Price;
						$trade_history->Fee = $this->FeePercentage * $trade_history->Unit * $trade_history->Price;
						$trade_history->MemberID = $this->MemberID;
						$trade_history->TradeSettingID = $this->TradeSettingID;
						$trade_history->write();
						$this->TradeHistories()->add($trade_history);
						
						$statement_data = array(
				            'Type' => 'Sell Share',
				            'Credit' => $trade_history->Amount * 0.5,
				            'Reference' => $trade_history->Reference,
				            'Description' => sprintf('Sell %s units of %s share at %s per unit. Fees %s, %s receivable.', $trade_history->dbObject('Unit')->Formatted(), $trade_history->Name, $trade_history->dbObject('Price')->Nice(), $trade_history->dbObject('Fee')->Nice(), DBField::create_field('Percentage', 0.5)->Nice())
				        );
				    	$id = BonusAccount::create_statement($statement_data, $trade_history->MemberID);
						$this->BonusAccounts()->add($id);
						
						$statement_data = array(
				            'Type' => 'Sell Share',
				            'Credit' => $trade_history->Amount * 0.1,
				            'Reference' => $trade_history->Reference,
				            'Description' => sprintf('Sell %s units of %s share at %s per unit. Fees %s, %s receivable.', $trade_history->dbObject('Unit')->Formatted(), $trade_history->Name, $trade_history->dbObject('Price')->Nice(), $trade_history->dbObject('Fee')->Nice(), DBField::create_field('Percentage', 0.1)->Nice())
				        );
				    	$id = ProductAccount::create_statement($statement_data, $trade_history->MemberID);
						$this->ProductAccounts()->add($id);
						
						$statement_data = array(
				            'Type' => 'Sell Share',
				            'Credit' => $trade_history->Amount * 0.3,
				            'Reference' => $trade_history->Reference,
				            'Description' => sprintf('Sell %s units of %s share at %s per unit. Fees %s, %s receivable.', $trade_history->dbObject('Unit')->Formatted(), $trade_history->Name, $trade_history->dbObject('Price')->Nice(), $trade_history->dbObject('Fee')->Nice(), DBField::create_field('Percentage', 0.3)->Nice())
				        );
				    	$id = TradeCoinAccount::create_statement($statement_data, $trade_history->MemberID);
						$this->TradeCoinAccounts()->add($id);
						
						$trade_history = TradeHistory::create();
						$trade_history->Type = 'Buy';
						$trade_history->Reference = $trade_order->Reference;
						$trade_history->Unit = $trade_order->Remaining;
						$trade_history->Price = $this->Price;
						$trade_history->Fee = $trade_order->FeePercentage * $trade_history->Unit * $trade_history->Price;
						$trade_history->MemberID = $trade_order->MemberID;
						$trade_history->TradeSettingID = $trade_order->TradeSettingID;
						$trade_history->write();
						$trade_order->TradeHistories()->add($trade_history);
						
						$this->Remaining -= $trade_order->Remaining;
						
						$trade_order->Remaining = 0;
						$trade_order->write();
						
						$this->Requesters()->add($trade_order);
					}
				}
				$this->write();
			}
			
		}
    }

	function getAction(){
		if($this->Status == 'Pending'){
	        $cancel_link = Controller::join_links(TradeMarketPage::get()->first()->Link('cancel'), $this->ID);
	        $action = sprintf('<a title="%s" class="btn btn-xs btn-primary" rel="tooltip" href="%s">%s</a>', _t('TradeOrder.CLICK_CANCEL_ORDER', 'Click here to cancel trade order'), $cancel_link, _t('TradeOrder.BUTTONCANCEL', 'Cancel'));
	
	        return $action;
		}
		return $this->Status;
    }
	
	function getName(){
		return $this->TradeSetting()->Title;
	}
	
	function getAmount(){
		return $this->Price * $this->Unit;
	}
	
	function getRemainAmount(){
		return $this->Price * $this->Remaining;
	}
	
	function getFee(){
		return $this->Amount * $this->FeePercentage;
	}
	
	function getRemainFee(){
		return $this->RemainAmount * $this->FeePercentage;
	}
	
	function canView($member = false) {
        $extended = $this->extendedCan(__FUNCTION__, $member);
        if($extended !== null) {
            return $extended;
        }
        return Permission::check('VIEW_TradeOrder');
    }

    function canEdit($member = false) {
        return false;
    }

    function canDelete($member = false) {
        return false;
    }

    function canCreate($member = false) {
        $extended = $this->extendedCan(__FUNCTION__, $member);
        if($extended !== null) {
            return $extended;
        }
        return Permission::check('CREATE_TradeOrder');
    }

    public function providePermissions() {
        return array(
            'VIEW_TradeOrder' => array(
                'name' => _t('TradeOrder.PERMISSION_VIEW', 'Allow view access right'),
                'category' => _t('TradeOrder.PERMISSIONS_CATEGORY', 'Trade Order')
            ),
            'CREATE_TradeOrder' => array(
                'name' => _t('TradeOrder.PERMISSION_CREATE', 'Allow create access right'),
                'category' => _t('TradeOrder.PERMISSIONS_CATEGORY', 'Trade Order')
            )
        );
    }
}
?>